<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ～ ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\wechat\repository;

use catchAdmin\permissions\middleware\PermissionsMiddleware;
use catchAdmin\wechat\model\WechatMenus;
use catcher\base\CatchRepository;
use catcher\exceptions\FailedException;
use catcher\library\WeChat;
use catcher\Tree;
use catcher\Utils;

class WechatMenusRepository extends CatchRepository
{
    protected $menus;

    public function __construct(WechatMenus $menus)
    {
        $this->menus = $menus;
    }

    protected function model()
    {
        return $this->menus;
    }

    public function all()
    {
        $menus = $this->menus->select();

        return Tree::done($menus->toArray());
    }

    /**
     * 新增
     *
     * @time 2020年06月26日
     * @param array $data
     * @return mixed
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\db\exception\DataNotFoundException
     */
    public function storeBy(array $data)
    {
        $parentId = $data['parent_id'] ?? 0;

        $this->checkMenuNum($parentId);

        $data['parent_id'] = $parentId;
        $data['key'] = $data['type'] . '_' . rand(10000, 999999);

        $data['created_at'] = $data['updated_at'] = time();

        if (parent::storeBy($data)) {
            return $this->syncToWechat();
        }// TODO: Change the autogenerated stub

        throw new FailedException('新增失败');
    }

    /**
     * 更新
     *
     * @time 2020年06月26日
     * @param int $id
     * @param array $data
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @return bool
     */
    public function updateBy(int $id, array $data)
    {
        $data['updated_at'] = time();

        if (parent::updateBy($id, $data)) {
            return $this->syncToWechat();
        }

        throw new FailedException('更新失败');
    }

    /**
     * 删除失败
     *
     * @time 2020年06月26日
     * @param int $id
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @return bool
     */
    public function deleteBy(int $id)
    {
        $menu = $this->findBy($id);

        // 父级菜单
        if (!$menu->parent_id) {
            if ($this->menus->where('parent_id', $id)->count()) {
                throw new FailedException('请先删除子级菜单');
            }
        }

        if (parent::deleteBy($id)) {
            return $this->syncToWechat();
        }

        throw new FailedException('删除失败');
    }

    /**
     * 同步
     *
     * @time 2020年06月26日
     * @throws \Exception
     * @return bool
     */
    public function sync()
    {
        // 同步前先删除
        $this->menus->where('id', '>', 0)->delete();

        $menus = WeChat::officialAccount()->menu->list()['menu']['button'];

        foreach ($menus as $menu) {
            $id = $this->menus->createBy($this->menuToLocal($menu));

            if (!empty($menu['sub_button'])) {
                foreach ($menu['sub_button'] as $button) {
                    $button['parent_id'] = $id;
                    $this->menus->createBy($this->menuToLocal($button));
                }
            }
        }

        return true;
    }

    /**
     * 同步到表
     *
     * @time 2020年06月26日
     * @param $menu
     * @return array
     */
    protected function menuToLocal($menu)
    {
        $data = [
            'parent_id' => $menu['parent_id'] ?? 0,
            'type' => $menu['type'] ?? '',
            'name' => $menu['name'],
            'key' => $menu['key'] ?? '',
            'created_at' => \time(),
            'updated_at' => \time(),
        ];

        if (isset($menu['type'])) {
            if ($menu['type'] == 'view') {
                $data['url'] = $menu['url'];
                return $data;
            } elseif ($menu['type'] == 'miniprogram') {
                $data['url'] = $menu['url'] ?? '';
                $data['appid'] = $menu['appid'];
                $data['pagepath'] = $menu['pagepath'];
                return $data;
            }
        }

        return $data;
    }


    /**
     * 同步到微信
     *
     * @time 2020年06月26日
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @return bool
     */
    protected function syncToWechat()
    {
       $menus =  $this->menus->field([
           'id', 'parent_id', 'key', 'name', 'type', 'url', 'appid', 'pagepath', 'media_id'
       ])->select()->toArray();

       foreach ($menus as &$menu) {
           if ($menu['type'] == 'view') {
               unset($menu['appid'], $menu['media_id'], $menu['pagepath']);
           } elseif ($menu['type'] == 'miniprogram') {
               unset($menu['media_id']);
           } else {
               unset($menu['url'], $menu['appid'], $menu['pagepath'], $menu['media_id']);
           }
       }

       $wechatMenus = Tree::done($menus, 0, 'parent_id', 'sub_button');

       WeChat::throw(WeChat::officialAccount()->menu->create($wechatMenus));

       return true;
    }

    /**
     * check menus number
     *
     * @time 2020年06月26日
     * @param $parentId
     * @return void
     */
    protected function checkMenuNum($parentId)
    {
        // 父级别分类
        if (!$parentId) {
            if ($this->menus->where('parent_id', 0)->count() >= 3) {
                throw new FailedException('只支持三个一级菜单');
            }
        } else {
            if ($this->menus->where('parent_id', $parentId)->count() >= 5) {
                throw new FailedException('只支持五个二级菜单');
            }
        }
    }
}